// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using BrainTechLLC.ThreadSafeObjects;
using System.Reflection;
using System.Runtime.Serialization;

namespace BrainTechLLC.Communication
{
    public class Message : ICommunicationsMessage
    {
        public Message()
        {
        }

        public Message(object o, int transmissionType, IMessageHeader header)
        {
            MessageContents = o;
            Header = header;
            Header.MessageType = transmissionType;
        }

        public Message(byte[] bytes, int transmissionType, IMessageHeader header)
        {
            Header = header;
            Header.MessageType = transmissionType;
            MessageContents = DeserializeCustom(transmissionType, bytes);
        }

        public object DeserializeCustom(int type, byte[] bytes)
        {
            Type t = type.TypeFromMessageType();

            if (t == null)
                return null;

            ConstructorInfo ci = t.GetConstructor(System.Type.EmptyTypes);
            ICanCustomSerialize o = ci.Invoke(null) as ICanCustomSerialize;

            if (o != null)
            {
                using (MemoryStream ms = new MemoryStream(bytes))
                {
                    using (BinaryReader b = new BinaryReader(ms))
                    {
                        o.SerializeIn(o, b);
                    }
                }
                return o;
            }

            return null;
        }

        public IMessageHeader Header
        {
            get;
            set;
        }

        public object MessageContents
        {
            get;
            set;
        }

        public int MessageType
        {
            get { return Header.MessageType; }
        }

        /// <summary>
        /// Creates a byte array for an object (with appropriate header bytes),
        /// allowing a message to be sent across the wire.
        /// </summary>
        public byte[] ReadBytesForTransmission()
        {
            byte[] commandBytes = null;
#if NO_SILVERLIGHT
            using (MemoryStream ms = new MemoryStream())
            {
                // Serialize the object to the memory stream starting at position 8
                using (BinaryWriter bw = new BinaryWriter(ms))
                {
                    // Leave the first 8 bytes empty for now
                    bw.Seek(Header.HeaderSize, SeekOrigin.Begin);
                    (MessageContents as ICanCustomSerialize).SerializeOut(bw);
                    // MessageContents.SerializeToCompressedBinaryMemoryStream(ms);

                    // Determine the byte length of the serialized object
                    Header.MessageSize = (int)ms.Length - Header.HeaderSize;

                    // Write the header to the beginning of the memory stream
                    Header.WriteHeaderToStream(ms);

                    commandBytes = ms.ToArray();
                }
            }
#endif
            return commandBytes;
        }
    }
}